package com.yanqu.road.server.manger.unioncampwar;

import com.yanqu.road.dao.impl.unioncampwar.UnionCampWarLockPatronsDaoImpl;
import com.yanqu.road.entity.config.battle.BattleUnionResult;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.servercenter.ChannelSystemConfig;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.union.cross.CrossUnionInfo;
import com.yanqu.road.entity.union.cross.CrossUnionMember;
import com.yanqu.road.entity.unioncampwar.config.UnionCampWarBuffConfig;
import com.yanqu.road.entity.unioncampwar.patrons.UnionCampWarLockPatronsData;
import com.yanqu.road.logic.bussiness.player.UserPatronsBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PatronsPb;
import com.yanqu.road.logic.pb.UnionCampWarPb;
import com.yanqu.road.pb.patrons.PatronsProto;
import com.yanqu.road.pb.unionCampWar.UnionCampWar;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.game.service.GameService;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.logic.battle.BattleManager;
import com.yanqu.road.server.manger.ChannelSystemConfigMgr;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.union.CrossUnionMgr;
import com.yanqu.road.server.manger.unioncampwar.service.UnionCampWarAttackPatronsCrossReqCmd;
import com.yanqu.road.server.manger.unioncampwar.service.UnionCampWarPatronsReqCmd;
import com.yanqu.road.server.manger.unioncampwar.service.UnionCampWarPatronsSyncCmd;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.utils.date.DateHelper;
import org.apache.mina.util.ConcurrentHashSet;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 管理开战期需要的商会所有门客数据
 */
public class UnionCampWarPatronsMgr extends TempMgr {
    //商会id 玩家id
    private static Map<String, UnionPatronsModel> unionPatronsMap = new ConcurrentHashMap<>();
    /**
     * 等待取所有门客的玩家id
     */
    private static Set<Long> waitTakePatronsUserList = new ConcurrentHashSet<>();


    @Override
    public boolean reloadData() throws Exception {
        int thisWeekId = GameConfig.getSystemThisWeekId();

        Map<String, List<UnionCampWarLockPatronsData>> dataTempMap = new UnionCampWarLockPatronsDaoImpl().getUnionCampWarLockPatronsDataMap();
        for (Map.Entry<String, List<UnionCampWarLockPatronsData>> entry : dataTempMap.entrySet()) {
            String unionUid = entry.getKey();
            UnionPatronsModel patronsModel = getPatronsModel(unionUid, true);
            for (UnionCampWarLockPatronsData lockPatronsData : entry.getValue()) {
                if (lockPatronsData.getUpdateTime() != thisWeekId) {
                    continue;
                }
                patronsModel.addPatronsData(lockPatronsData);
            }
        }

        return true;
    }

    public static void reloadSystemConfig() {
        ConfigMgr.parseUnionCampWarConfig();

        ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());

        Map<String, ChannelSystemConfig> systemConfigMap = ChannelSystemConfigMgr.getSystemConfigMap(serverInfo.getChannelId(), eSystemId.UnionCampWar.getValue());
        if (systemConfigMap != null && systemConfigMap.containsKey("SHANGBANG_LOTTERY_COST")) {
            ConfigMgr.getUnionCampWarConfig().setSHANGBANG_LOTTERY_COST(systemConfigMap.get("SHANGBANG_LOTTERY_COST").getValue());
        }
    }

    public static void addSystemReloadNotify() {
        ChannelSystemConfigMgr.addReloadListener(() -> {
            reloadSystemConfig();
            getLogger().info("UnionCampWarPatronsMgr.reloadSystemConfig() 重新加载商会战配置");
        });
    }

    @Override
    public boolean save() {
        int systemThisWeekId = GameConfig.getSystemThisWeekId();

        Map<String, UnionPatronsModel> tempMap = new HashMap<>(unionPatronsMap);

        List<String> removeUnionIdList = new ArrayList<>();
        for (Map.Entry<String, UnionPatronsModel> entry : tempMap.entrySet()) {
            String unionId = entry.getKey();
            boolean isNeedRemove = true;
            boolean empty = entry.getValue().getAllSavePatronsList().isEmpty();
            if (empty) {
                isNeedRemove = false;
            }
            for (UnionCampWarLockPatronsData lockPatronsData : entry.getValue().getAllSavePatronsList()) {
                if (lockPatronsData.isInsertOption()) {
                    new UnionCampWarLockPatronsDaoImpl().add(lockPatronsData);
                } else if (lockPatronsData.isUpdateOption()) {
                    new UnionCampWarLockPatronsDaoImpl().update(lockPatronsData);
                }

                if (lockPatronsData.getUpdateTime() == systemThisWeekId) {
                    isNeedRemove = false;
                }
            }

            if (isNeedRemove){
                removeUnionIdList.add(unionId);
            }
        }

        for (String unionId : removeUnionIdList){
            unionPatronsMap.remove(unionId);
        }

        return true;
    }

    @Override
    public boolean init() throws Exception {
        addSystemReloadNotify();
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        reloadSystemConfig();
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    public static void initService(GameService syncMessageService) {
        syncMessageService.addGameServiceCommand(GameProtocol.S_UNION_CAMP_WAR_PATRONS_INFO_SYNC, new UnionCampWarPatronsSyncCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_UNION_CAMP_WAR_PATRONS_INFO_REQ, new UnionCampWarPatronsReqCmd());
        syncMessageService.addGameServiceCommand(GameProtocol.S_UNION_CAMP_WAR_ATTACK_TEAM_CROSS_REQ, new UnionCampWarAttackPatronsCrossReqCmd());
    }

    public static UnionPatronsModel getPatronsModel(String unionId, boolean newIfNull) {
        UnionPatronsModel patronsModel = unionPatronsMap.get(unionId);
        if (null == patronsModel && newIfNull) {
            synchronized (unionPatronsMap) {
                patronsModel = unionPatronsMap.get(unionId);
                if (null == patronsModel) {
                    patronsModel = new UnionPatronsModel(unionId);
                    unionPatronsMap.put(unionId, patronsModel);
                }
            }
        }

        return patronsModel;
    }

    public static List<UnionPatronsModel> getPatronsModelList() {
        List<UnionPatronsModel> list = new ArrayList<>();
        synchronized (unionPatronsMap) {
            list.addAll(unionPatronsMap.values());
        }
        return list;
    }


    public static void addNeedTakePatronsUser(Long userId) {
        synchronized (waitTakePatronsUserList) {
            waitTakePatronsUserList.add(userId);
        }
    }

    public static void takePatronsTask() {
        List<Long> userIdList = new ArrayList<>();
        synchronized (waitTakePatronsUserList) {
            userIdList.addAll(waitTakePatronsUserList);
            waitTakePatronsUserList.clear();
        }
        long thisWeekId = GameConfig.getSystemThisWeekId();
        for (Long userId : userIdList) {
            CrossUnionMember unionMember = CrossUnionMgr.getUnionMember(userId);
            if (null == unionMember) {
                continue;
            }
            CrossUnionInfo unionInfo = CrossUnionMgr.getUnionInfo(unionMember.getUnionUid());
            if (unionInfo == null) {
                continue;
            }
            List<UserPatrons> userPatronsList;
            GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
            if (null != player) {
                userPatronsList = player.getModule(PatronsModule.class).getUserPatronsList();
            } else {
                userPatronsList = new ArrayList<>(UserPatronsBussiness.getUserPatronsMap(userId).values());
            }

            if (unionInfo.getServerId() == GameServer.getInstance().getServerId()) {
                UnionPatronsModel patronsModel = getPatronsModel(unionInfo.getUnionUid(), true);
                for (UserPatrons userPatrons : userPatronsList) {
                    UnionCampWarLockPatronsData lockPatronsData = UnionCampWarPb.parseLockPatronData(unionInfo.getUnionUid(), userPatrons);
                    lockPatronsData.setUpdateTime(thisWeekId);
                    patronsModel.addPatronsData(lockPatronsData);
                }

                if (userPatronsList.isEmpty()){//运营测试的号是有可能没有门客的，防错
                    UnionCampWarLockPatronsData lockPatronsData = new UnionCampWarLockPatronsData();
                    lockPatronsData.setUnionId(unionInfo.getUnionUid());
                    lockPatronsData.setUserId(userId);
                    lockPatronsData.setPatronsId(0);
                    lockPatronsData.setUpdateTime(thisWeekId);
                    patronsModel.addPatronsData(lockPatronsData);
                }
            } else {
                UnionCampWar.CrossUnionCampWarPatronsSyncMsg.Builder syncMsg = UnionCampWar.CrossUnionCampWarPatronsSyncMsg.newBuilder();
                syncMsg.setUnionId(unionInfo.getUnionUid());
                syncMsg.setUserId(userId);
                for (UserPatrons userPatrons : userPatronsList) {
                    PatronsProto.PatronsSimpleTempMsg.Builder patronsMsg = PatronsPb.parsePatronsSimpleTempMsg(userPatrons);
                    syncMsg.addPatronsInfo(patronsMsg);
                }
                GamePlayerMgr.sendToGameServer(unionInfo.getServerId(), GameProtocol.S_UNION_CAMP_WAR_PATRONS_INFO_SYNC, 0, syncMsg, null);
            }
        }
    }

    /**
     * 从其他游戏服同步过来的门客数据
     *
     * @param syncMsg
     */
    public static void receivePatronsSyncMsg(UnionCampWar.CrossUnionCampWarPatronsSyncMsg syncMsg) {
        String unionId = syncMsg.getUnionId();
        UnionPatronsModel patronsModel = getPatronsModel(unionId, true);
        long userId = syncMsg.getUserId();
        long thisWeekId = GameConfig.getSystemThisWeekId();
        for (PatronsProto.PatronsSimpleTempMsg patronsSimpleTempMsg : syncMsg.getPatronsInfoList()) {
            UnionCampWarLockPatronsData lockPatronsData = UnionCampWarPb.parseLockPatronData(unionId, userId, patronsSimpleTempMsg);
            lockPatronsData.setUpdateTime(thisWeekId);
            patronsModel.addPatronsData(lockPatronsData);
        }
    }

    /**
     * 商会跨服向游戏服请求门客总数,检查商会所有成员的门客都有了没,有了就传总门客数到据点
     */
    public static int getUnionAllPatronsNum(String unionId, List<Long> memberIds) {
        UnionPatronsModel patronsModel = getPatronsModel(unionId, true);
        if (null == patronsModel) {
            return 0;
        }

        if (!CrossUnionMgr.isAllSync()) {
            return 0;
        }

        boolean allSync = true;
        long thisWeekId = GameConfig.getSystemThisWeekId();

        CrossUnionInfo unionInfo = CrossUnionMgr.getUnionInfo(unionId);
        if (unionInfo != null) {//防止玩家在拉门客数据时离会导致问题。
            memberIds = CrossUnionMgr.getUnionMemberIdList(unionInfo.getUnionUid());
        }

        for (Long memberId : memberIds) {
            CrossUnionMember unionMember = CrossUnionMgr.getUnionMember(memberId);
            if (null == unionMember) {
                unionMember = CrossUnionMgr.getUnionMember("", memberId);
            }
            if (null == unionMember) {
                continue;
            }

            if (patronsModel.isNeedSyncPatrons(unionMember.getUserId(), thisWeekId)) {
                allSync = false;

                if (unionMember.getServerId() == GameServer.getInstance().getServerId()) {
                    addNeedTakePatronsUser(unionMember.getUserId());
                } else {
                    UnionCampWar.CrossUnionCampWarPatronsReqMsg.Builder reqMsg = UnionCampWar.CrossUnionCampWarPatronsReqMsg.newBuilder();
                    reqMsg.setUnionId(unionMember.getUnionUid());
                    reqMsg.setUserId(unionMember.getUserId());
                    GamePlayerMgr.sendToGameServer(unionMember.getServerId(), GameProtocol.S_UNION_CAMP_WAR_PATRONS_INFO_REQ, 0, reqMsg, null);
                }
            }
        }

        if (allSync) {
            return patronsModel.getAllPatronsNum();
        }

        return 0;

    }

    public static UnionCampWar.CrossUnionCampWarToGameAttackRespMsg.Builder battle(UnionCampWar.CrossUnionCampWarToGameAttackReqMsg reqMsg) {
        UnionCampWar.CrossUnionCampWarToGameAttackRespMsg.Builder respMsg = UnionCampWar.CrossUnionCampWarToGameAttackRespMsg.newBuilder();
        respMsg.setIsWin(false);

        List<Long> unionMemberIdList = CrossUnionMgr.getUnionMemberIdList(reqMsg.getTargetUnionId());

        UnionPatronsModel patronsModel = getPatronsModel(reqMsg.getTargetUnionId(), false);
        if (null == patronsModel) {
            //热更修复,如果被回收,会重新请求成员门客数据
            int unionAllPatronsNum = getUnionAllPatronsNum(reqMsg.getTargetUnionId(), unionMemberIdList);
            getLogger().error("商帮门客数据等待重新同步,商会={}", reqMsg.getTargetUnionId());
            return null;
        } else {
            int unionAllPatronsNum = patronsModel.getAllPatronsNum();
            if (0 == unionAllPatronsNum) {
                getUnionAllPatronsNum(reqMsg.getTargetUnionId(), unionMemberIdList);
                //门客数据还没同步到
                getLogger().error("商帮门客数据等待重新同步,商会={}", reqMsg.getTargetUnionId());
                return null;
            }
        }
        Map<Long, CrossUnionMember> unionMemberMap = CrossUnionMgr.getUnionMemberMap(reqMsg.getTargetUnionId());

        List<UnionCampWarLockPatronsData> randomPatronsList = patronsModel.getRandomPatronsList();

        UnionCampWarBuffConfig buffConfig = ConfigMgr.getUnionCampWarConfig().getBuffConfig(reqMsg.getBuffId());

        List<UserPatrons> defendPatrons = new ArrayList<>();
        List<UserPatrons> attackPatrons = new ArrayList<>();
        for (UnionCampWarLockPatronsData lockPatronsData : randomPatronsList) {
            defendPatrons.add(UnionCampWarPb.parseUserPatronsByLockPatrons(lockPatronsData));
        }
        for (PatronsProto.PatronsSimpleTempMsg patronsSimpleTempMsg : reqMsg.getPatronsInfoList()) {
            attackPatrons.add(UnionCampWarPb.parseUserPatronsByPatronsMsg(reqMsg.getUserId(), patronsSimpleTempMsg));
            respMsg.addPatronsIdList(patronsSimpleTempMsg.getPatronsId());
        }

        //战斗
        BattleUnionResult battleUnionResult = BattleManager.battleByUnionCampWar(reqMsg.getUserId(), attackPatrons, reqMsg.getTargetUnionId(), defendPatrons, buffConfig, reqMsg.getAvgAbilityList());
        if (battleUnionResult.getDefeatedEnemyPatronsList().size() == defendPatrons.size()) {
            respMsg.setIsWin(true);
        }

        //附加战斗详情
        UnionCampWar.UnionCampWarBattleDetailListMsg.Builder detailListMsg = UnionCampWarPb.parseBattleDetailListMsg(battleUnionResult.getPatronsBattleDetailList());
        respMsg.setBattleDetailList(detailListMsg);
        for (UserPatrons userPatrons : battleUnionResult.getDefeatedEnemyPatronsList()) {
            UnionCampWar.UnionCampBattlePatronsDetailTemp.Builder enemyPatronsMsg = UnionCampWar.UnionCampBattlePatronsDetailTemp.newBuilder();
            enemyPatronsMsg.setEnemyUserId(userPatrons.getUserId());
            enemyPatronsMsg.setEnemyUserName("");
            CrossUnionMember member = unionMemberMap.get(userPatrons.getUserId());
            if (null != member) {
                enemyPatronsMsg.setEnemyUserName(member.getUserBaseInfo().getNickName());
            }
            enemyPatronsMsg.setPatronsInfo(PatronsPb.parsePatronsSimpleTempMsg(userPatrons));
            respMsg.addEnemyPatronsList(enemyPatronsMsg);
        }
        if (!respMsg.getIsWin()) {
            UserPatrons userPatrons = battleUnionResult.getLastFightEnemyPatrons();
            UnionCampWar.UnionCampBattlePatronsDetailTemp.Builder enemyPatronsMsg = UnionCampWar.UnionCampBattlePatronsDetailTemp.newBuilder();
            enemyPatronsMsg.setEnemyUserId(userPatrons.getUserId());
            enemyPatronsMsg.setEnemyUserName("");
            CrossUnionMember member = unionMemberMap.get(userPatrons.getUserId());
            if (null != member) {
                enemyPatronsMsg.setEnemyUserName(member.getUserBaseInfo().getNickName());
            }
            enemyPatronsMsg.setPatronsInfo(PatronsPb.parsePatronsSimpleTempMsg(userPatrons));
            respMsg.addEnemyPatronsList(enemyPatronsMsg);
        }

        respMsg.setDefeatNum(battleUnionResult.getKillPatronsCount());
        respMsg.setUserId(reqMsg.getUserId());
        respMsg.setTargetUnionId(reqMsg.getTargetUnionId());

        return respMsg;
    }

}
